//===============================================================================
// Copyright (C) 2008 Charles River Media. All rights reserved.
// 
// Catmull-Clark subdivision surface viewer program
//
// The developer of the code is
// Gyorgy Antal <gyantal@gmail.com>
//
// Contributor(s):
// Laszlo Szirmay-Kalos <szirmay@iit.bme.hu>
//
// The software was developed for the chapter 
// "Fast Evaluation of Subdivision Surfaces on DirectX10 Graphics Hardware"
// of the book ShaderX 6: Advanced Rendering Techniques, 
// edited by Wolfgang Engel,
// the appropriate section edited by Tom Forsyth. 
//
// The files are provided without support, instruction, or implied warranty of any
// kind.  Charles River Media makes no guarantee of its fitness for a particular purpose and is
// not liable under any circumstances for any damages or loss whatsoever arising
// from the use or inability to use this file or items derived from it.
//===============================================================================
// File: Scanner.h
//
// Description:
//===============================================================================

#include "file.h"

//===================================================================
// TOKEN DEFINITIONS
//===================================================================
#define Token			int

enum BaseTokens {
	EOF_TOKEN = -1,
	NUMBER_TOKEN = -2,
	NAME_TOKEN = -3,
	ERROR_TOKEN = -4
};

//===================================================================
// BUFFER
//===================================================================
#define MAXTOKENBUFFER  2048    /* length of a given syntatic construct   */
typedef long Number;

//------------------------------------------------------------------
// Strores parameters of the actual token
//------------------------------------------------------------------
class TokenBuffer {                                   
//-------------------------------------------------------------------
    char    buffer[MAXTOKENBUFFER]; // character string
    int     buff_ptr;               // buffer pointer
public:                                                                 
    TokenBuffer()   { buff_ptr = 0; }

    void    Clear(void )    { buff_ptr = 0; }              
    void    Put(char data );  // Put character and advance pointer
    char *  Get(void )             // Get string stored in buffer
                        { buffer[buff_ptr] = '\0'; return buffer; }   
};

//---------------------------------------------------------------
struct SpecialChar {
//---------------------------------------------------------------
    char special;
    Token  token;
public:
    int  Match(char c )  { return (special == c); }
    int  Match(Token t ) { return (token == t); }
    Token GetToken()     { return token; }
    char GetChar()       { return special; }  
};

//---------------------------------------------------------------
class SpecialCharTable {
//---------------------------------------------------------------
	int			  nspecials;
    SpecialChar * specials;
public:
	SpecialCharTable(SpecialChar * spec, int nspec ) { specials = spec; nspecials = nspec; }
    char    FindSpecial(Token tok );
    Token   FindToken(char c );
};

//---------------------------------------------------------------
struct Keyword {
//---------------------------------------------------------------
    char * keyword;
    Token  token;
public:
    int  Match(char * key ) { return (!strcmp(keyword,key)); }
	int  Comp(char * key)   { return strcmp(key, keyword); }
    int  Match(Token  t )   { return (token == t); }
    Token GetToken()        { return token; }
    char * GetKeyword()     { return keyword; }
};

extern int keyf[];
//---------------------------------------------------------------
class KeywordTable {
//---------------------------------------------------------------
	int		  nkeys;
	Keyword * keywords;
public :
	KeywordTable(Keyword * keys, int nk ) { keywords = keys; nkeys = nk; }
    Token   FindToken(char * key );
	Token   FindNumToken(int tok );
    char *  FindKeyword(Token tok );
};

//---------------------------------------------------------------
// SCANNER STATE MACHINE                                         
// Separates input stream into tokens
//---------------------------------------------------------------
class Scanner : public InputFile {
//---------------------------------------------------------------
    int              line_pos, char_pos;     // actual location
    char             curr_char, next_char;   // actual and next character
    TokenBuffer      token_buffer;           // parameter of act token
    KeywordTable     keys;                   // reserved names
    SpecialCharTable special_chars;
    Token            current_token;

    char	Read();                        // get next char and advance
protected:
    int IsEOF(char c )					  { return (int)(c == EOF); }
    virtual BOOL IsCommentBegin(char c ) { return FALSE; }
	virtual BOOL IsCommentEnd(char c)	  { return FALSE; } 
    virtual BOOL IsWhite(char c )		  { return (int)(' ' == c || c == '\t' || c == '\r' ); }
    virtual BOOL IsLetter(char c )		  { return (int)(('0'<= c && c <='9') ||
												         ('a'<= c && c <='z') ||
														 ('A'<= c && c <= 'Z') || 
														 ('_' == c )); }
    int IsDecimal(char c )				  { return (int)('0'<= c && c <= '9');  }
    int IsMinus(char c )				  { return (int)(c == '-'); }
    int IsDot(char c )					  { return (int)(c == '.'); }

public:
    Scanner(char * n, SpecialChar * specs, int npecs, Keyword * keywords, int nkeys ) 
		: InputFile(n ), special_chars(specs, npecs ), keys(keywords, nkeys ) { line_pos = char_pos = 0; }
	Token     		GetToken() ;                    // get next token
	Token     		GetCurrentToken() { return current_token; }

    char *          GetName() ;             // match & get parameter string
    Number          GetNumber() ;           // match & get stored number
    float           GetReal() ;             // match & get stored number
    void            Location(int& line, int& row ) // get location
                            { line = line_pos; row = char_pos; }
    void            Match(Token t ) ;
    void            Error(char * mess );
};
